<?php
/**
 * crcl/base
 *
 * Copyright 2013 CRCL - André Sabosch - info@crcl.de
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace crcl\base\application;

interface IPath
{
  /**
   * Replaces all application specific constants
   * @see replace
   * @see replaceDirectories
   *
   * @param string $sInput string to replace
   */
  public static function replaceConstants($sInput);

  /**
   * Returns Namespace for project: \vendor\project\
   *
   * @return  string
   */
  public static function getNamespace();

  /**
   * Returns Namespace for subproject: \vendor\project\subproject\
   *
   * @return  string
   */
  public static function getNamespaceSubproject();

  /**
   * Returns project url from application data, depends on Tier
   *
   * @param string $sType optional url subtype (URL_STATIC_CSS, URL_STATIC_JS, URL_STATIC_IMG)
   *
   * @return  string  URL
   */
  //public static function getUrl($sType = \NULL);

  /**
   * Returns input string with replaced application vars
   *
   * @param string  $sInput
   *
   * @return mixed  replaced string
   */
  public static function replace($sInput);

  /**
   * Returns directory from given type
   * @see DIR_* constants
   *
   * @param string  $sType
   *
   * @return  string  directory
   */
  public static function getDirectory($sType);

  /**
   * Resets cache
   */
  public static function resetCache();
}

class Path implements IPath
{
  // etc/vendor/project/common/configs/
  const DIR_CONFIGS = 'DIR_APPLICATION_CONFIGS';
  // etc/vendor/project/common/items/
  const DIR_ITEMS = 'DIR_APPLICATION_ITEMS';
  // etc/vendor/project/subprojectname/controller/
  const DIR_CONTROLLER = 'DIR_APPLICATION_CONTROLLER';
  // etc/vendor/project/subprojectname/templates/
  const DIR_TEMPLATES = 'DIR_APPLICATION_TEMPLATES';
  // httpdocs/static/css/version/
  const DIR_STATIC_CSS = 'DIR_APPLICATION_STATIC_CSS';
  // httpdocs/static/js/version/
  const DIR_STATIC_JS = 'DIR_APPLICATION_STATIC_JS';
  // httpdocs/static/img/version/
  const DIR_STATIC_IMG = 'DIR_APPLICATION_STATIC_IMG';

  const VAR_APPLICATION = '%APPLICATION%';
  const VAR_APPLICATION_VENDOR = '%APPLICATION_VENDOR%';
  const VAR_APPLICATION_PROJECT = '%APPLICATION_PROJECT%';
  const VAR_APPLICATION_SUBPROJECT = '%APPLICATION_SUBPROJECT%';

  //static.prj.vendor.tier.crcl.de/css/version
  //const URL_STATIC_CSS = 'URL_APPLICATION_STATIC_CSS';
  //static.prj.vendor.tier.crcl.de/js/version
  //const URL_STATIC_JS = 'URL_APPLICATION_STATIC_JS';
  //static.prj.vendor.tier.crcl.de/img/version
  //const URL_STATIC_IMG = 'URL_APPLICATION_STATIC_IMG';

  public static function getDirectory($sType)
  {
    \crcl\base\Application::testIdentifierSet();

    if (isset(self::$aCacheDirectories[$sType]))
    {
      return self::$aCacheDirectories[$sType];
    }
    $sDir = \NULL;
    switch ($sType)
    {
      case self::DIR_TEMPLATES:
        $sDir = self::getDirectoryEtcProject();
        $sDir .= \crcl\base\Application::getSubProject() . '/templates/';
        break;
      case self::DIR_CONTROLLER:
        $sDir = self::getDirectoryEtcProject();
        $sDir .= \crcl\base\Application::getSubProject() . '/controller/';
        break;
      case self::DIR_CONFIGS:
        $sDir = self::getDirectoryEtcProject();
        $sDir .= 'common/configs/';
        break;
      case self::DIR_ITEMS:
        $sDir = self::getDirectoryEtcProject();
        $sDir .= 'common/items/';
        break;
/*      case self::DIR_STATIC_CSS:
        $sDir = self::getDirectoryHttpdocs();
        $sDir .= 'static/css/';
        $sDir .= Config::reader()->get('static', 'css');
        $sDir .= '/';
        break;
      case self::DIR_STATIC_JS:
        $sDir = self::getDirectoryHttpdocs();
        $sDir .= 'static/js/';
        $sDir .= Config::reader()->get('static', 'js');
        $sDir .= '/';
        break;
      case self::DIR_STATIC_IMG:
        $sDir = self::getDirectoryHttpdocs();
        $sDir .= 'static/img/';
        $sDir .= Config::reader()->get('static', 'img');
        $sDir .= '/';
        break; */
      default:
        throw new Exception(
          'Invalid type', Exception::ERROR_INVALIDTYPE, array('type' => $sType));
    }

    $oDir = new \crcl\base\File($sDir);
    $sDir = $oDir->toString(); //convert slashes

    self::$aCacheDirectories[$sType] = $sDir;

    return $sDir;
  }

  public static function getNamespace()
  {
    $sResult = '\\' . \crcl\base\Application::getVendor() . '\\' .
      \crcl\base\Application::getProject() . '\\';
    return $sResult;
  }

  public static function getNamespaceSubproject()
  {
    $sResult = self::getNamespace();
    $sResult .= \crcl\base\Application::getSubProject() . '\\';
    return $sResult;
  }
/*
  public static function getUrl($sType = \NULL)
  {
    if (\is_null($sType))
    {
      $sSubProject = \crcl\base\Application::getSubProject();
    }
    elseif (($sType == self::URL_STATIC_CSS) ||
            ($sType == self::URL_STATIC_JS) || ($sType == self::URL_STATIC_IMG)
    )
    {
      $sSubProject = 'static';
    }

    $sResult = 'http://' .
      $sSubProject . '.' .
      \crcl\base\Application::getProject() . '.' .
      \crcl\base\Application::getVendor() . '.' .
      \strtolower(\crcl\base\Tier::get()) .
      '.crcl.de';
    if (\crcl\base\Tier::isProduction())
    {
      $sResult = \crcl\base\Config::reader()->get('static', 'url');
    }
    if ($sType == self::URL_STATIC_CSS)
    {
      $sResult .= '/css/' . Config::reader()->get('static', 'css') . '/';
    }
    if ($sType == self::URL_STATIC_JS)
    {
      $sResult .= '/js/' . Config::reader()->get('static', 'js') . '/';
    }
    if ($sType == self::URL_STATIC_IMG)
    {
      $sResult .= '/img/' . Config::reader()->get('static', 'img') . '/';
    }
    return $sResult;
  }
*/
  public static function replace($sInput)
  {
    $sReturn = $sInput;
    if (\strpos($sInput, '%') !== \FALSE)
    {
      $sReturn = \str_replace(self::VAR_APPLICATION_SUBPROJECT, \crcl\base\Application::getSubProject(), $sReturn);
      $sReturn = \str_replace(self::VAR_APPLICATION_PROJECT, \crcl\base\Application::getProject(), $sReturn);
      $sReturn = \str_replace(self::VAR_APPLICATION_VENDOR, \crcl\base\Application::getVendor(), $sReturn);
      $sReturn = \str_replace(self::VAR_APPLICATION, \crcl\base\Application::getIdentifier(), $sReturn);
    }
    return $sReturn;
  }

  public static function replaceConstants($sInput)
  {
    $sInput = self::replaceDirectories($sInput);
    $sInput = self::replace($sInput);
    return $sInput;
  }

  public static function resetCache()
  {
    self::$aCacheDirectories = array();
  }

  /** PROTECTED ***********************************************************************************/
  
  /** PRIVATE *************************************************************************************/

  private static $aCacheDirectories = array();

  private static function getDirectoryEtcProject()
  {
    $sDir = \dirname(\dirname(\dirname(\dirname(__FILE__))));
    $sDir .= DIRECTORY_SEPARATOR;
    $sDir .= \crcl\base\Application::getGroup();
    $sDir .= DIRECTORY_SEPARATOR;
    return $sDir;
  }

/*  private static function getDirectoryHttpdocs()
  {
    $sDir = \dirname(\dirname(\dirname(\dirname(__FILE__))));
    $sDir .= DIRECTORY_SEPARATOR . 'httpdocs' . DIRECTORY_SEPARATOR;
    return $sDir;
  }
*/
  private static function replaceDirectories($sPath)
  {
    if (\strlen($sPath))
    {
      $sPath = self::replaceDirectory($sPath, self::DIR_CONFIGS);
      $sPath = self::replaceDirectory($sPath, self::DIR_TEMPLATES);
      $sPath = self::replaceDirectory($sPath, self::DIR_CONTROLLER);
    }
    return $sPath;
  }

  private static function replaceDirectory($sPath, $sSearch)
  {
    $sDirectory = self::getDirectory($sSearch);
    $sSearch = '%' . $sSearch . '%';
    $iPos = \strpos($sPath, $sSearch);
    if ($iPos !== \FALSE)
    {
      if ($iPos > 0)
      {
        if ($sPath[$iPos - 1] == '/')
        {
          $sDirectory = \crcl\base\String::getInstance($sDirectory)
            ->doNotStartWith('/')
            ->toString();
          //drive letter, windows?
          if (\strlen($sDirectory) > 2)
          {
            if ($sDirectory[1] == ':') //Drive letter
            {
              $sPath = \substr($sPath, 0, $iPos - 1) . \substr($sPath, $iPos);
              //calculate new iPos for next test
              $iPos = \strpos($sPath, $sSearch);
            }
          }
        }
      }
      if (\strlen($sPath) > $iPos + \strlen($sSearch))
      {
        if ($sPath[$iPos + \strlen($sSearch)] == '/')
        {
          $sDirectory = \crcl\base\String::getInstance($sDirectory)
            ->doNotEndWith('/');
        }
      }
      $sPath = \str_replace($sSearch, $sDirectory, $sPath);
    }
    return $sPath;
  }
}